﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using PlanningGIS.Statistics ;
using PlanningGIS.Statistics;
using PlanningGIS.Framework.Controls;
using PlanningGIS.Framework;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.esriSystem;
using PlanningGIS.Win.Controls;
using PlanningGIS.ArcGIS;
using PlanningGIS.Report;

namespace PlanningGIS.Statistics
{
    /// <summary>
    /// 说明：该类是为衢州用户的新需求新增的植被统计类，要求是植被要素需要
    ///       扣除房屋面和道路面（房屋和道路都需要指定相应的缓冲距离）的相
    ///       交部分，该程序频繁调用ITopologicalOperator，速度较慢。
    /// 编写者：张忠胜
    /// 编写时间：2010.7.5
    /// </summary>
    internal class NewVegStatButton : BaseDrawPolygonTool
    {
        private IElement m_pElement;
        private FrmReport m_pReport;
        private IFeatureLayer pFeatureLayer;
        //private AxMapControl pMapControl;
        private string strID = "植被面";
        private StatLayer m_pStatLyr = null;
        private DataTable m_pTable = null;
        IApplication m_Application = null;
        private IMapControl3 pMapControl = null;

        public NewVegStatButton()
        {
            base.m_caption = "绿化率统计ext";
            base.m_toolTip = base.m_caption;
            m_cursor = Cursors.Cross;
        }

        public override void OnCreate(object hook)
        {
            m_Application = hook as IApplication;
            base.OnCreate(hook);
        }

        public override bool Enabled
        {
            get
            {
                
                if ((m_Application as IFramework).IsMapCtrlactive)
                {
                    IEnumLayer layers = (m_Application.Document as IMxDocument).ActiveView.FocusMap.get_Layers(null, true);
                    ILayer layer = layers.Next();
                    while (layer != null)
                    {
                        if (layer is IFeatureLayer)
                        {
                            Marshal.ReleaseComObject(layers);
                            return true;
                        }
                        layer = layers.Next();
                    }
                    Marshal.ReleaseComObject(layers);
                }
                return false;
            }
        }

        public override void OnClick()
        {
            if ((m_Application as IFramework).Tool == this) return;
            base.OnClick();

            //IMapControl3 pMapControl = null;
            if ((m_Application as IFramework).IsMapCtrlactive)
                pMapControl = (m_Application as IFramework).MapControl;
            else
                return;

            if (pMapControl == null || pMapControl.Map.LayerCount == 0) return;

            pFeatureLayer = null;
            m_pStatLyr = StatFactory.GetLayerByID(strID);
            if (m_pStatLyr == null)
            {
                MsgHelper.ShowInfomationMsgbox("尚未找到植被面层，请加载植被面层！");
                return;
            }
            pFeatureLayer = MapHelper.GetFirstLayer<IFeatureLayer>(pMapControl.Map, m_pStatLyr.Value);
            if (pFeatureLayer == null)
            {
                MsgHelper.ShowInfomationMsgbox("尚未找到植被面层，请加载植被面层！");
                return;
            }
        }

        public override int Bitmap
        {
            get
            {
                string bitmapResourceName = "PlanningGIS.Statistics.Res." + this.GetType().Name + ".png";
                System.IO.Stream s = GetType().Assembly.GetManifestResourceStream(bitmapResourceName);
                if (s == null) return 0;
                return new Bitmap(s).GetHbitmap().ToInt32(); 
            }
        }

        public override void OnDblClick()
        {
            base.OnDblClick();
            FrmVegStatPara veg = new FrmVegStatPara();
            if (veg.ShowDialog() == DialogResult.OK)
            {
                Hashtable pHash = veg.Parameters;

                if (pHash == null) { return; }
                if (m_geom == null || m_geom.IsEmpty) { return; }
                if (m_pTable == null)
                {
                    m_pTable = CreateVegetableDatatable();
                }
                else if (m_pTable.Rows.Count > 0)
                {
                    m_pTable.Rows.Clear();
                }

                IPolygon pPolygon = m_geom as IPolygon;
                ITopologicalOperator2 pTopo = pPolygon as ITopologicalOperator2;
                pTopo.IsKnownSimple_2 = false;
                pTopo.Simplify();
                pTopo.IsKnownSimple_2 = true;
                pPolygon.Project(((IGeoDataset)pFeatureLayer.FeatureClass).SpatialReference );

                Application.DoEvents();
                ISpatialFilter pSF = new SpatialFilterClass();
                pSF.Geometry = pPolygon;
                pSF.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
                pSF.WhereClause = m_pStatLyr.WhereClause();
                IFeatureCursor pFeatureCursor = pFeatureLayer.FeatureClass.Search(pSF, false);
                IFeature pFeature = pFeatureCursor.NextFeature();
                while (pFeature != null)
                {
                    AddDatarow(m_pTable, pFeature, m_geom, pHash);
                    pFeature = pFeatureCursor.NextFeature();
                }
                if (m_pTable.Rows.Count == 0)
                {
                    MsgHelper.ShowInfomationMsgbox("尚未检索到植被面要素，请重试！");
                    pMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
                    return;
                }
                if (m_pReport == null || m_pReport.IsDisposed)
                {
                    m_pReport = new FrmReport();
                }

                IArea pArea = m_geom as IArea;
                double dblArea = Math.Abs(pArea.Area);
                // 
                if (m_geom.SpatialReference is IGeographicCoordinateSystem)
                {
                    ISpatialReference pSpatialReference = GeometryHelper.GetSpatialByX(pArea.Centroid.X);
                    IClone pClone = m_geom as IClone;
                    IGeometry pGeomClone = pClone.Clone() as IGeometry;
                    pGeomClone.Project(pSpatialReference);
                    pArea = pGeomClone as IArea;
                    dblArea = pArea.Area;
                }
                // 

                if (dblArea < 0.000001) return;
                if (m_pReport == null || m_pReport.IsDisposed)
                {
                    m_pReport = new FrmReport();
                }
                m_pReport.DataSource = m_pTable;
                m_pReport.ParameterValue = dblArea;
                m_pReport.FullName = AppConfig.StartupPath + @"\Report\Statistic\绿化率统计报表.rpt";
                m_pReport.Title = "绿化率统计报表";
                if (!m_pReport.Visible) m_pReport.Show((m_Application as IFramework).MdiForm);
                m_pReport.RefreshReport();
            }
            pMapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);

        }
        
        private DataTable CreateVegetableDatatable()
        {
            DataTable pTable = new DataTable();

            foreach (ReportField  field in m_pStatLyr.ReportFields)
            {
                DataColumn pColumn = new DataColumn(field.Key );
                pColumn.DataType = Type.GetType("System." + field.Type);
                if (field.Type.ToLower().Contains("int"))
                {
                    pColumn.DefaultValue = 0;
                }
                else if (field.Type.ToLower().Contains("double"))
                {
                    pColumn.DefaultValue = 0.00;
                }
                pTable.Columns.Add(pColumn);
            }

            return pTable;
        }

        private void AddDatarow(DataTable pTable, IFeature pFeature, IGeometry pGeo, Hashtable pHash)
        {
            if (pFeature == null || pTable == null) { return; }
            DataRow pRow = pTable.NewRow();
            IFields PFields = pFeature.Fields;
            int idx = -1;
            foreach (ReportField  field in m_pStatLyr.ReportFields)
            {
                switch (field.Key )
                {
                    case "OID":
                        pRow[field.Key] = pFeature.OID.ToString();
                        break;
                    case "FCODE":
                        idx = pFeature.Fields.FindField(field.Value);
                        if (idx > -1)
                        {
                            pRow[field.Key] = pFeature.get_Value(idx).ToString();
                        }
                        break;
                    case "NAME":
                    case "FDESC":
                        idx = pFeature.Fields.FindField(field.Value);
                        if (idx > -1)
                        {
                            if (pFeature.get_Value(idx) == null || Convert.IsDBNull(pFeature.get_Value(idx)))
                            {
                                pRow[field.Key] = "";
                            }
                            else
                            {
                                pRow[field.Key] = pFeature.get_Value(idx).ToString();
                            }
                        }
                        break;
                    case "AREA":
                        IPolygon pPolygon = pFeature.ShapeCopy as IPolygon;
                        pRow[field.Key] = GetVegetableArea(pPolygon, pHash);
                        break;
                    default:
                        break;
                }
            }

            pTable.Rows.Add(pRow);
        }
        
        private double GetVegetableArea(IPolygon pPg, Hashtable pHash)
        {
            try
            {
                foreach (DictionaryEntry de in pHash)
                {
                    string strLyrName = de.Key.ToString();
                    string strDist = de.Value.ToString();
                    StatLayer lyr = StatFactory.GetLayerByID(strLyrName);
                    IFeatureLayer pTempLyr = MapHelper.GetFirstLayer<IFeatureLayer>(pMapControl.Map, strLyrName);
                    if (pTempLyr == null)
                    {
                        MsgHelper.ShowInfomationMsgbox(strLyrName + "未找到！");
                        continue;
                    }
                    ISpatialFilter pFilter = new SpatialFilterClass();
                    ITopologicalOperator pTopo = pPg as ITopologicalOperator;
                    pFilter.Geometry = pTopo.Buffer(double.Parse(strDist));
                    pFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
                    pFilter.WhereClause = lyr.WhereClause();
                    IFeatureCursor pCursor = pTempLyr.FeatureClass.Search(pFilter, false);
                    IRelationalOperator pRela = pPg as IRelationalOperator;
                    IFeature pFeature = pCursor.NextFeature();
                    while (pFeature  != null)
                    {
                        IGeometry pTempGeo = pFeature.ShapeCopy;
                        ITopologicalOperator pTempTopo = pTempGeo as ITopologicalOperator;
                        IGeometry pTempGeo1= pTempTopo.Buffer(double.Parse(strDist));
                        if (pRela.Overlaps(pTempGeo1))
                        {
                            pTopo = pPg as ITopologicalOperator;
                            IGeometry pGeo1 = pTopo.Difference(pTempGeo1);
                            if (pGeo1 == null || pGeo1.IsEmpty)
                            {
                                continue;
                            }
                            else
                            {
                                pPg = pGeo1 as IPolygon;
                            }
                        }
                        pFeature = pCursor.NextFeature();
                    }
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pCursor); 
                }
                IArea pArea = pPg as IArea;
                return Math.Abs(pArea.Area);
            }
            catch (Exception ex)
            {
                return 0;
            }
        }


    }
}
